package com.lwj.log;


import org.apache.commons.io.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class LogRequestWrapper extends HttpServletRequestWrapper {
	private byte[] buffer;
	private ServletInputStream in;
	private BufferedReader reader;

	public LogRequestWrapper(HttpServletRequest request) throws IOException {
		super(request);
		buffer = IOUtils.toByteArray(request.getInputStream());
		in = new CachedServletInputStream(buffer);
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		if (in != null) {
			return in;
		}
		return super.getInputStream();
	}

	@Override
	public BufferedReader getReader() throws IOException {
		if (reader == null) {
			reader = new BufferedReader(new InputStreamReader(in, getCharacterEncoding()));
		}
		return reader;
	}
	@Override
	public String getCharacterEncoding() {
		String charsetName = super.getCharacterEncoding();
		charsetName = charsetName != null ? charsetName : "utf-8";
		return charsetName;
	}

	/**
	 * 获取请求内容
	 * 
	 * @return
	 * @throws Exception
	 */
	public String getContent() throws Exception {
		String charsetName = getCharacterEncoding();
		return getContent(charsetName);
	}
	/**
	 * 获取请求内容
	 * 
	 * @param charsetName
	 * @return
	 * @throws Exception
	 */
	public String getContent(String charsetName) throws Exception {
		StringBuilder content = new StringBuilder();
		String params = requestParameters();
		content.append(params);
		String contentByteArray = new String(getContentAsByteArray(), charsetName).replaceAll("[\\t\\n\\r]", "");
		if (params != null && params.length() > 0 && contentByteArray != null && contentByteArray.length() > 0) {
			content.append(" , ");
		}
		content.append(contentByteArray);
		return content.toString();
	}

	public byte[] getContentAsByteArray() {
		return buffer;
	}

	public String requestParameters() {
		StringBuilder msg = new StringBuilder();
		try {
			String requestEncoding = getCharacterEncoding();
			@SuppressWarnings("unchecked")
            Map<String, String[]> form = super.getParameterMap();
			for (Iterator<String> nameIterator = form.keySet().iterator(); nameIterator.hasNext();) {
				String name = nameIterator.next();
				List<String> values = Arrays.asList(form.get(name));
				for (Iterator<String> valueIterator = values.iterator(); valueIterator.hasNext();) {
					String value = valueIterator.next();
					msg.append(URLEncoder.encode(name, requestEncoding));
					if (value != null) {
						msg.append('=');
						msg.append(URLEncoder.encode(value, requestEncoding));
						if (valueIterator.hasNext()) {
							msg.append('&');
						}
					}
				}
				if (nameIterator.hasNext()) {
					msg.append('&');
				}
			}
		} catch (IOException ex) {
			throw new IllegalStateException("Failed to write request parameters to cached content", ex);
		}
		return msg.toString();
	}

	public class CachedServletInputStream extends ServletInputStream {

		private final ByteArrayInputStream bais;

		public CachedServletInputStream(byte[] bytes) {
			bais = new ByteArrayInputStream(bytes);
		}

		@Override
		public int read() throws IOException {
			return bais.read();
		}
		@Override
		public boolean isFinished() {
			return bais.available() == 0;
		}
		@Override
		public boolean isReady() {
			return true;
		}

		@Override
		public void setReadListener(ReadListener readListener) {

		}

	}

}